% \iffalse
%<*driver>
\ProvidesFile{swufethesis.dtx}
%</driver>
%<class>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<class>\ProvidesClass{swufethesis}
[2021/03/14 1.0.0-alpha.0 Southwestern University of Finance and Economics Thesis Template]
%
%<*driver>
\documentclass{swufedoc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% \input{\jobname-doc}
% \StopEventually{}
% \section{实现细节}
% 这里是文档类\textsf{swufethesis}的具体实现细节。对于文档的正常使用来说，是不需要查询这里的内容的。
% \subsection{宏包选项}
% 设定选项互补选项 |openright| 和 |openany| 并传递给基类。
% 设定选项 |nobib| 决定是否需要设置参考文献。
% 由于 \pkg{biblatex} 需要在 preamble 里调用 \cs{addbibresource}，故需要将是否由 \cls{swufethesis} 设定参考文献的决定提前至载入类的时候。
%    \begin{macrocode}
\RequirePackage{kvoptions}
\RequirePackage{kvdefinekeys}
\RequirePackage{etoolbox}
\DeclareBoolOption[false]{nobib}
\DeclareBoolOption[false]{openright}
\DeclareComplementaryOption{openany}{openright}
\DeclareDefaultOption{\PassOptionsToClass{\CurrentOption}{ctexbook}}
\ProcessKeyvalOptions{swufethesis}
\ifswufethesis@openright
  \PassOptionsToClass{openright}{ctexbook}
\else
  \PassOptionsToClass{openany}{ctexbook}
\fi
%    \end{macrocode}
% \subsection{宏包和类文件的加载}
% 文档类\cls{swufethesis}基于\cls{ctexbook}。对于\pkg{tocloft}宏包，启用 |titles|选项
% 使其采用\pkg{ctex}的章节标题设定。\pkg{emptypage} 宏包的作用是使 \cs{cleardoublepage} 等命令添加的页面不含页码。
%    \begin{macrocode}
\LoadClass[scheme=plain,zihao=-4,fontset=none]{ctexbook}
\RequirePackage{xparse}
\RequirePackage{filehook}
\RequirePackage{xeCJKfntef}
\RequirePackage{geometry}
\RequirePackage{fancyhdr}
\RequirePackage[titles]{tocloft}
\RequirePackage{caption}
\RequirePackage{graphicx}
\ifswufethesis@nobib\else
  \RequirePackage[style=gb7714-2015,sorting=gb7714-2015]{biblatex}
\fi
\RequirePackage{unicode-math}
\RequirePackage{emptypage}
%    \end{macrocode}
%
% \subsection{用户接口设置}
% \begin{macro}{\swufesetup}
% 通过键值对的方式来传入用户的设置是一种比较常见的方式，
% 用户选项传递的标准方式是宏包的选项机制，但是对于较多的选项设置，
% 我们更希望提供一个专用的宏\cs{swufesetup}给用户，使得用户能够方便地用这个宏通过键值对的方式
% 来设置\cls{swufethesis}的选项，这也是现在用的比较多的一种机制。
% \pkg{kvsetkeys}宏包提供了相关的宏来解析一组键值对列表，所以\cs{swufesetup}本质上是
% 对宏\cs{kvsetkeys}的一个包装。我们只需要对每一个选项设置相应的handler即可，具体的handler
% 设定是在\cs{swufe@define@key}里实现的。
%    \begin{macrocode}
\newcommand\swufesetup[1]{%
  \kvsetkeys{swufe}{#1}%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@foreach}
% \pkg{kvsetkeys}提供的遍历键值对列表加handler的机制可以看作是一种forEach，所以
% 可以借此实现一个，但是这不能和其他的handler嵌套。（没有想象中的好用，考虑移除）。
% \cs{swufe@foreach}接受两个参数，第一个是键值对列表，第二个是handler的定义，
% 定义中可以使用 |#1|和 |#2|分别作为遍历时键与值。
%    \begin{macrocode}
\newcommand{\swufe@foreach}[2]{
  \def\swufe@@foreach@family{swufe@foreach}%
  \kv@set@family@handler{\swufe@@foreach@family}{#2}%
  \expandafter\kvsetkeys\expandafter{%
  \expandafter\swufe@@foreach@family\expandafter}\expandafter{#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\swufe@define@key}
% 下面提供一个命令\cs{swufe@define@key}，可以按下面的方式定义一组用户选项。
% 为了可读性，用户选项名可能含有一些特殊字符如“*”、“-”等，所以可通过\meta{name}来指定别名，
% 方便内部宏名的设定。而\meta{choices}则可为这个选项设定可选值。
% \begin{latex}
% \swufe@define@key{
%   <key> = {
%     name = <name>,
%     choices = { <value1>, <value2> },
%   }
% }
% \end{latex}
% 按以上的方式使用之后，当用户按下面的方式调用\cs{swufesetup}时，则会根据\meta{choices}（如果有设置的话）
% 检查\meta{input}是否是合理的，并设置相应的\cs{ifswufe@\meta{name}@\meta{choice}}，
% 同时将\meta{input}存储到\cs{swufe@\meta{name}}中。
% \begin{latex}
% \swufesetup{
%   <name> = <input>
% }
% \end{latex}
%    \begin{macrocode}
\newcommand{\swufe@define@key}[1]{%
  \kvsetkeys{swufe@key}{#1}
}
%    \end{macrocode}
% \end{macro}
% 下面即是 |swufe@key|的handler。对于每一个\meta{key}，我们需要处理\meta{name}和\meta{choices}。 
%    \begin{macrocode}
\kv@set@family@handler{swufe@key}{%
%    \end{macrocode}
% 定义\cs{swufe@\meta{key}@name}存储别名。
%    \begin{macrocode}
  \@namedef{swufe@#1@name}{#1}
  \kv@define@key{swufe@value}{name}{%
    \@namedef{swufe@#1@name}{##1}
  }
%    \end{macrocode}
% 对\meta{choices}里的每个\meta{choice}定义\cs{ifswufe@\meta{name}@\meta{choice}}来存储
% 枚举类型。
%    \begin{macrocode}
  \@namedef{swufe@#1@choices}{}
  \kv@set@family@handler{swufe@choices}{%
    \expandafter\newif\csname ifswufe@\@nameuse{swufe@#1@name}@##1\endcsname
  }
  \kv@define@key{swufe@value}{choices}{%
    \@namedef{swufe@#1@choices}{##1}
    \kvsetkeys{swufe@choices}{##1}
    \@namedef{swufe@#1@choices}{##1}
  }
%    \end{macrocode}
% 为这个选项定义一个钩子宏\cs{swufe@@\meta{key}@code}，它将在\cs{swufesetup}被调用时调用。我们待会可以通过
% \cs{g@addto@macro}这种方式来修改它的定义。
%    \begin{macrocode}
  \@ifundefined{swufe@@#1@code}{\@namedef{swufe@@#1@code}{}}{}
%    \end{macrocode}
% 执行上面定义的handler来处理\meta{name}和\meta{choices}。
% 并为\cs{swufe@\meta{name}}定义空值，增加后面的容错性。
%    \begin{macrocode}
  \kvsetkeys{swufe@value}{#2}
  \@namedef{swufe@\@nameuse{swufe@#1@name}}{}
%    \end{macrocode}
%
% 为\cs{swufesetup}设置handler，这里才是\cs{swufesetup}的真正实现部分。
% 即为相应的选项设置\cs{swufe@\meta{name}}的值存储用户的输入，并调用
% \cs{swufe@@check}来检查用户传入的值，最后调用这个选项的钩子宏\cs{swufe@@\meta{key}@code}。
%
%    \begin{macrocode}
  \kv@define@key{swufe}{#1}{%
    \@namedef{swufe@\@nameuse{swufe@#1@name}}{##1}
    \expandafter\ifx\csname swufe@#1@choices\endcsname\@empty\else%
      \swufe@@check{#1}{##1}%
    \fi%
    \@nameuse{swufe@@#1@code}
  }
}
%    \end{macrocode}
%
% \begin{macro}{\swufe@@check}
% \cs{swufe@@check}接受第一个参数为选项名，第二个参数为待检测的选项值，
% 根据该选项预设的可选值来决定是否报错。如果传入值合理，则将相应的条件宏
% \cs{ifswufe@\meta{name}@{choice}}置为真，其他的置为假。
%    \begin{macrocode}
\newcommand{\swufe@@check}[2]{
  \@ifundefined{ifswufe@\@nameuse{swufe@#1@name}@#2}{\ClassError{swufethesis}{%
      Invalid value #2 for option #1%
    }{}}%
  \edef\swufe@@choices{\@nameuse{swufe@#1@choices}}
  \swufe@foreach{\swufe@@choices}{%
    \@nameuse{swufe@\@nameuse{swufe@#1@name}@##1false}%
  }
  \@nameuse{swufe@\@nameuse{swufe@#1@name}@#2true}%
}
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\swufe@option@hook}
% 定义\cs{swufe@option@hook}\marg{key}\marg{macro}来修改相应选项的钩子\cs{swufe@@\meta{key}@code}。
% 第一个参数是该选项的\meta{key}，第二个参数是要追加的宏。
%    \begin{macrocode}
\newcommand{\swufe@option@hook}[2]{%
  \expandafter\g@addto@macro\csname swufe@@#1@code\endcsname{#2}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{定义用户接口}
% 用上面的\cs{swufe@define@key}定义我们需要的用户接口。包括届数、日期、题目、格式类型等。
%    \begin{macrocode}
\swufe@define@key{
%    \end{macrocode}
% 届数
%    \begin{macrocode}
  index,
  date,
  title,
  title* = {
      name = title@en,
    },
  author,
  school,
  discipline,
  student-id = {
      name = student@id
    },
  supervisor,
  degree = {
      choices = {
          bachelor,
          master,
          doctor,
        }
    },
  output = {
      choices = {
          print,
          electronic,
        }
    },
  usage = {
    choices = {
      normal,
      check,
      anon,
    },
  },
%    \end{macrocode}
% 硕士学位类型，分别为学术型、专业型和同等学力。以及研究生的学位类别、研究方向。
%    \begin{macrocode}
  degree-type = {
      name = degree@type,
      choices = {
          academic,
          professional,
          equivalent,
        }
    },
  degree-in = {
      name = degree@in,
  },
  research-field = {
      name = research@field,
  },
  secret-level = {
      name = secret@level,
    },
  secret-year = {
      name = secret@year,
    },
%    \end{macrocode}
% 分类号。
%    \begin{macrocode}
  clc,
  udc,
  cjk-font = {
      name = cjk@font,
      choices = {
          auto,
          windows,
          mac,
          noto,
          fandol,
          none,
        }
    },
  font = {
      choices = {
          auto,
          times,
          termes,
        }
    },
}
%    \end{macrocode}
% \subsubsection{一些工具宏设定}
% 这里是一些内部用到工具宏，包括日期格式的转换和逗号分隔列表转字符串。
% \begin{macro}{\swufe@twodigits}
% 将\cs{month}和\cs{day}转为两位数
%    \begin{macrocode}
\def\swufe@twodigits#1{\ifnum#1<10 0\fi\the#1}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@join@clist}
% 将逗号分隔列表转为特定分隔符间隔的字串。
%    \begin{macrocode}
\newcommand{\swufe@join@clist}[2]{%
  \def\swufe@tmp{}%
  \newcommand{\swufe@clist@processor}[1]{%
    \ifx\swufe@tmp\@empty
      \def\swufe@tmp{#2}%
    \else
      #2%
    \fi
    ##1%
  }%
  \expandafter\comma@parse\expandafter{#1}{\swufe@clist@processor}
}
%    \end{macrocode}
%\end{macro}
% \begin{macro}{\swufe@date@format}
% 这个宏接受一个 |YYYY-MM-DD|的日期和一个宏，然后会把年月日作为3个参数传递给那个宏。
% 定义里面的|\@nil|是参数表达式的一部分（一个常见的写法，本身无意义），
% 用于标识参数的结束，否则最后的日期将只有一位数被纳入参数。
%    \begin{macrocode}
\newcommand{\swufe@date@format}[2]{%
  \def\swufe@@date@format@processor##1-##2-##3\@nil{%
    #2{##1}{##2}{##3}
  }%
  \expandafter\swufe@@date@format@processor#1\@nil
}
%    \end{macrocode}
% \end{macro}
% 下面的宏则是具体的日期格式转换器，它们接收年月日3个参数并输出特定日期格式。
% \begin{macro}{\swufe@date@zh@digit}
% 转化为 |YYYY年MM月DD日|。
%    \begin{macrocode}
\newcommand{\swufe@date@zh@digit}[3]{%
  #1年\number#2月\number#3日
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@date@zh@digit@short}
% 与上面的相同，但是不包含日期。
%    \begin{macrocode}
\newcommand{\swufe@date@zh@digit@short}[3]{
  #1年#2月
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@index@formatter}
% 根据日期的年月转化为相应的届数。逻辑是届数等于当前年份，如果月份大于8，则再加一。
%^^A 若在\fi后面使用\relax会使封面的届数数字后面多些空白（尚不清楚原理）
%    \begin{macrocode}
\newcommand{\swufe@index@formatter}[3]{%
  \the\numexpr#1 \ifnum#2>8 + 1\fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\swufe@chapter*}
% 该命令是\cs{chapter*}的拓展，可将未编号的章节纳入目录。
% \begin{center}
% \cs{swufe@chapter*}\oarg{tocline}\marg{title}
% \end{center}
% 参数 |tocline|表示该章节在目录中的条目，默认与 |title|相同，留空表示不纳入目录。
%    \begin{macrocode}
\NewDocumentCommand\swufe@chapter{s o m}{%
  \chapter*{#3}%
  \IfValueTF{#2}{%
    \ifthenelse{\equal{#2}{}}{}{%
      \addcontentsline{toc}{chapter}{#2}%
    }%
  }{\addcontentsline{toc}{chapter}{#3}}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{行距字号设定}
% 正文1.5倍行距。实际上使用的是单倍行距，对于MS Word来说，在开启到对齐到网格情况下，
% 1.5倍行距指是行距为行跨度的1.5倍，而行跨度与基础字号有关，但是由于未知原因，\footnote{可能是feature吧。}
% 即使修改了基础字号，如果不去修改页面布局的设定（包括调整后又调回来再点确定），
% 行跨度是不会变化的。所以正文小四号字体下的行跨度与默认的正文五号字相同---为15.6磅。
%
% 本科生毕业论文的格式规范是1.5倍行距，研究生是1.37倍行距。
%    \begin{macrocode}
\swufe@option@hook{degree}{%
  \ifswufe@degree@bachelor%
    \renewcommand{\normalsize}{\fontsize{12bp}{1.5\dimexpr 15.6pt}\selectfont}
  \else%
    \renewcommand{\normalsize}{\fontsize{12bp}{1.37\dimexpr 15.6pt}\selectfont}
  \fi%
}
%    \end{macrocode}
% \subsection{页面设置}
% 本科生页边距上下左右都为3厘米，研究生上3.9厘米，下3.4厘米，左右3.45厘米。
% 同时研究生要求页眉2.8厘米，页脚2.5厘米，这里的实际距离是根据MS Word的样式调整的。
%    \begin{macrocode}
\swufe@option@hook{degree}{%
  \setlength{\headheight}{24pt}
  \ifswufe@degree@bachelor%
    \geometry{
      a4paper,
      left=3cm,
      top=3cm,
      right=3cm,
      bottom=3cm,
    }
  \else%
    \geometry{
      a4paper,
      top=3.9cm,
      bottom=3.4cm,
      left=3.45cm,
      right=3.45cm,
      headsep=20pt,
      foot=21pt,
    }
  \fi
}
%    \end{macrocode}
% \subsection{章节标题}
% 对章节标题进行汉化和格式调整。
%    \begin{macrocode}
\ifswufe@degree@bachelor
  \ctexset{
    chapter/format = \CJKfamily{xbs}\fontsize{22bp}{1.5\dimexpr15.6pt}%
    \bfseries\centering\selectfont,
  }
\else
  \ctexset{
    chapter/format = \CJKfamily{hwzs}\fontsize{22bp}{1.5\dimexpr15.6pt}%
    \bfseries\centering\selectfont,
  }
\fi
\ctexset{
  autoindent = true,
  contentsname = 目录,
  listfigurename = 插图,
  listtablename = 表格,
  figurename = 图,
  tablename = 表,
  indexname = 索引,
  appendixname = 附录,
  bibname = 参考文献,
  proofname = 证明,
  chapter = {
    name = {,.},
    afterindent = true,
    aftername = \quad,
    titleformat = {},
    fixskip = true,
%    \end{macrocode}
% 这里需要说明的是，与chapter不同，section与subsection的 |beforeskip|
% 仅在前面为段落（非标题）时起作用。
% 而Word的策略是取段前段后最大的距离作为间距，这里由于二三级标题的要求是
% 段前段后都为一行而恰好可以满足。
% 第二点是section与subsection的 |beforeskip|作为页面的起始也是不生效的，
% 这一点与Word相同，除非那个地方是一个新节（而一般仅在章这一层次使用分节符，
% 从而与\LaTeX 的chapter吻合）。
% 下面chapter, section, subsection的 |beforeskip|与 |afterskip|皆是通过视觉效果调整。
%    \begin{macrocode}
    beforeskip = 48pt,
    afterskip = 50pt,
   },
  section = {
    name = {,.},
    afterindent = true,
    format = \sffamily\fontsize{15bp}{1.5\dimexpr 15.6pt }\selectfont,
    fixskip = true,
    beforeskip = 30pt,
    afterskip = 30pt,
   },
  subsection = {
      name = {,.},
      afterindent = true,
      format = \sffamily\fontsize{12bp}{1.5\dimexpr 15.6pt}\selectfont,
      fixskip = true,
      beforeskip = 28pt,
      afterskip = 28pt,
    }
}
%    \end{macrocode}
% \subsection{Three matters}
% 我们先修改 \cs{cleardoublepage} 的定义，给右开增加一个前提——非 |electronic| 模式，从而在 |electronic| 模式下将不会因为右开产生空白页。
%    \begin{macrocode}
\let\swufe@oldcleardoublepage\cleardoublepage
\renewcommand{\cleardoublepage}{%
  \ifswufe@output@electronic%
    \clearpage%
  \else%
    \swufe@oldcleardoublepage%
  \fi%
}
%    \end{macrocode}
% 重新定义\cs{frontmatter}、\cs{mainmatter}与\cs{backmatter}。
% \begin{macro}{\frontmatter}
% \cs{frontmatter} 标记正文前内容开始编写页码的地方。
% 根据规范，本科生论文的页码通篇都要用阿拉伯数字，且中英摘要都是重新编号；
% 研究生论文则未作规定，采用书籍排版上常用的罗马数字。
% 对于研究生论文来说，\cs{maketitle} 同时输出封面与扉页，而对封面编码一般说来并不符合排版规律，故规定：
% 从页码的角度，\cs{maketitle} 视作仅仅输出扉页，忽略封面的存在。
% 即使说 \cs{maketitle} 和 \cs{frontmatter} 的相对关系决定了是否从扉页开始计数。
% 所以我们设置 \cs{ifswufe@frontmatter}，在 \cs{maketitle} 输出扉页时以决定是否需要重设页码。
%    \begin{macrocode}
\newif\ifswufe@frontmatter%
\renewcommand{\frontmatter}{%
  \cleardoublepage%
  \ifswufe@degree@bachelor%
    \pagenumbering{arabic}%
  \else%
    \pagenumbering{Roman}%
  \fi%
  \swufe@frontmattertrue%
  \@mainmatterfalse%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\mainmatter}
% \cs{mainmatter}标记正文的开始。
%    \begin{macrocode}
\renewcommand{\mainmatter}{%
  \cleardoublepage%
  \@mainmattertrue
  \swufe@frontmatterfalse%
  \pagenumbering{arabic}%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\backmatter}
% \cs{backmatter}标记附录的结束。同时如果开启检测版的选项，则\cs{backmatter}
% 之后的内容不再输出。
%    \begin{macrocode}
\renewcommand{\backmatter}{%
  \ifswufe@usage@check\end{document}\fi % 检测版直接结束
  \@mainmatterfalse%
  \cleardoublepage%
}
%    \end{macrocode}
% \end{macro}
% \subsection{目录}
% \begin{macro}{\tableofcontents}
% 目录的相关设定。目录的字号字体与正文相同，同时大标题与章节标题相同。
% 这里为了让目录重新开始编号并右开，重新定义了一下\cs{tableofcontents}。
% 本科毕业论文要求中英文摘要各自从阿拉伯数字 1 开始编码，对于目录没有作说明。
% 从文章逻辑上讲，目录没有理由接续英文摘要的编码，也将其设置为从阿拉伯数字 1 开始。
%    \begin{macrocode}
\renewcommand{\cftchapfont}{\bfseries}
\let\swufe@tableofcontents\tableofcontents
\def\tableofcontents{%
  \cleardoublepage%
  \ifswufe@degree@bachelor%
    \pagenumbering{arabic}%
  \fi%
  \swufe@tableofcontents%
}
%    \end{macrocode}
% \end{macro}
% \subsection{图表标题}
% 使用\pkg{caption}设置图表标题样式为五号字体单倍行距。
%^^A TODO: 五号字体采用的是\cs{small}指代，可能不是很合适。
%    \begin{macrocode}
\captionsetup{
  font={sf,bf,small},
  justification=centering,
  labelsep=quad,
  aboveskip=0.5\baselineskip,
  belowskip=0.5\baselineskip,
  parskip=0.5\baselineskip,
}
%    \end{macrocode}
% 修改图表编号格式为X-X。
%    \begin{macrocode}
\renewcommand{\thetable}{\thechapter-\arabic{table}}
\renewcommand{\thefigure}{\thechapter-\arabic{figure}}
%    \end{macrocode}
% 重新定义\env{table}环境以实现表格内容五号字单倍行距（字体未作规定）。
% \begin{environment}{table}
%    \begin{macrocode}
\let\swufe@oldtable\table
\def\table[#1]{\swufe@oldtable[#1]\fontsize{10.5bp}{10.5bp}}
%    \end{macrocode}
%\end{environment}
%
% \subsection{摘要与关键词}
% 定义 \env{abstract} 与 \env{abstract*} 环境。
% 根据本科毕业论文规范，中英文摘要各自都需要从阿拉伯数字 1 开始编码。
% \begin{environment}{abstract}
% 中文摘要\env{abstract}。
%    \begin{macrocode}
\newenvironment{abstract}[1]{%
  \cleardoublepage%
  \ifswufe@degree@bachelor%
    \pagenumbering{arabic}%
  \fi%
  \chapter{摘要}%
  \newcommand{\swufe@keywords}{#1}%
}{%
%    \end{macrocode}
% 对于比较长的摘要，这里禁止断页后，\LaTeX 会优先调整段落间距来使关键词与最后一页摘要在同一页，
% 可能会出现某一段落间距比普通的长一行的高度
% （但一般是一页仅有两个段落时才会出现这种情况，多个段落会分摊这些间距）。
%^^A TODO: 也许有方法可以让前一页提前断页，即这一行空白出现在前一页末尾而不是被段落间距分摊，这样也许会好看一点
%    \begin{macrocode}

  \nopagebreak
  \vspace{\baselineskip}
  \noindent\textbf{关键词：\swufe@join@clist{\swufe@keywords}{；}}
}
%    \end{macrocode}
% \end{environment}
% \begin{environment}{abstract*}
% 英文摘要\env{abstract*}。
%    \begin{macrocode}
\newenvironment{abstract*}[1]{%
  \cleardoublepage%
  \ifswufe@degree@bachelor%
    \pagenumbering{arabic}%
  \fi%
  \chapter{Abstract}%
  \newcommand{\swufe@keywords@en}{#1}%
}{%

  \nopagebreak
  \vspace{\baselineskip}
  \noindent\textbf{Keywords: \swufe@join@clist{\swufe@keywords@en}{; }}
}
%    \end{macrocode}
% \end{environment}
%
% \subsection{页眉页脚}
% 通过\pkg{fancyhdr}设置页眉页脚样式。由于章节页面默认使用\textsf{plain}样式。
% 我们将\textsf{plain}的样式也置为\textsf{fancy}。
% 为了设置中文的页眉，使用了\pkg{ctex}中的\cs{CTEXifname}与\cs{CTEXthechapter}等命令，
% 其中\cs{CTEXifname}表示标题不被编号时则不显示，详见其文档。
% 实际上，通过 \pkg{fancyhdr}，我们可以越过 \LaTeX\ 内建的 \cs{leftmark}、\cs{rightmark} 等来直接设置页眉。
% 但考虑到兼容性，我们仍需要正确地配置 \cs{sectionmark}、\cs{chaptermark} 的行为，
% 通过 \cs{markboth}、\cs{markleft}、\cs{markright} 来配置 \cs{leftmark}（章名）以及 \cs{rightmark}（节名）这种具有意义的全局变量。
%    \begin{macrocode}
\newcommand{\swufe@set@fancyhf}{%
  \pagestyle{fancy}
  \fancyhf{}
  \ifswufe@degree@bachelor
    \fancyfoot[C]{\zihao{-5}\thepage}
    \renewcommand{\headrulewidth}{0pt}
  \else
    \fancyhead[RO]{\zihao{-5}\leftmark}
    \fancyhead[LE]{\zihao{-5}\swufe@title}
    \fancyfoot[RO]{\zihao{-5}\thepage}
    \fancyfoot[LE]{\zihao{-5}\thepage}
    \renewcommand{\headrulewidth}{1pt}
  \fi
  \fancypagestyle{plain}{}
  \renewcommand\chaptermark[1]{%
    \markboth{\CTEXifname{\CTEXthechapter}{}##1}{}%
  }
  \renewcommand\sectionmark[1]{%
    \markright{\CTEXthesection##1}%
  }
}
\AtBeginDocument{%
  \swufe@set@fancyhf
}
%    \end{macrocode}
% \subsection{致谢}
% \begin{environment}{acknowledgments}
% 将“致谢”定义成一个环境比较方便使用。
%    \begin{macrocode}
\newenvironment{acknowledgments}{%
  \chapter{致谢}
}{}
%    \end{macrocode}
% \end{environment}
% \subsection{封面与扉页}
% \begin{environment}{swufe@msword@geometry}
% 虽然规范上要求上下左右页边距为3cm，但实际给出的封面与申明页模板采用的Word默认页边距
% 为达到一致的视觉效果，对封面页和申明页使用特别的页边距，并在其他页面重置
%    \begin{macrocode}
\newenvironment{swufe@msword@geometry}{%
  \newgeometry{%
    vmargin=2.54cm,
    hmargin=3.18cm,
  }%
}{\restoregeometry}
%    \end{macrocode}
% \end{environment}
% \begin{macro}{\maketitle}
% 重新定义\cs{maketitle}来打印封面与扉页（如果有）。根据用户的设置来具体调用相应打印命令。
% 本科生的检测版论文 |usage = check| 将不再打印封面。
%    \begin{macrocode}
\renewcommand{\maketitle}{%
  \newif\ifswufe@should@maketitle%
  \swufe@should@maketitletrue%
  \ifswufe@usage@check%
    \ifswufe@degree@bachelor%
      \swufe@should@maketitlefalse%
    \fi%
  \fi%
  \ifswufe@should@maketitle%
    \begin{swufe@msword@geometry}
      \cleardoublepage%
      \thispagestyle{empty}%
      \ifswufe@degree@bachelor%
        \swufe@make@bachelor@cover%
      \else%
        \swufe@make@postgraduate@cover%
        \cleardoublepage%
        \thispagestyle{empty}%
        \swufe@make@postgraduate@titlepage%
      \fi%
    \end{swufe@msword@geometry}
  \fi%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@conditional@center@underline}
% 封面里面常常有表单一样的排版，例如“学号：417XXXXX”，其中“417XXXXX”需要有下划线并居中；
% 同时我们也希望在值较长时，能够自然地断行而不居中。这个宏就实现了这样的功能：如果文本短于一行，则居中，并有延长至两端的下划线；
% 如果是一行以上，则不居中，且末端的下划线尽可能延长。
% 它的实现原理在于将文本存在盒子里，并判断盒子的长度。可以参考 Stack Exchange 上的回答\footnote{\url{https://tex.stackexchange.com/a/16329}}。
% 事实上，浮动体标题 \cs{caption} 就是这样实现的。
% 另外也有通过 \cs{prevgraf} 实现的例子\footnote{\url{https://tex.stackexchange.com/a/97080}}，即判断前一自然段的行数，故这种方式依赖于换段，在表格环境中会引起多余的行。
%    \begin{macrocode}
\NewDocumentCommand{\swufe@conditional@center@underline}{m}{%
  \noindent%
  \newbox\somelittlebox%
  \savebox\somelittlebox{#1}%
  \let\ep\expandafter%
  \ifdim\wd\somelittlebox>\hsize%
    \CJKunderline*{#1\hfill}%
  \else%
    \CJKunderline*{\hfill#1\hfill}%
  \fi%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@make@bachelor@cover}
% 本科生封面。由于“届数”与数字之间间距相较于MS Word来是过大，于是特别调整了\textsf{CJKecglue}，
% 之后再还原成默认设置（参见\pkg{xeCJK}的文档的代码实现部分的初始化设置）。
%    \begin{macrocode}
\newcommand{\swufe@make@bachelor@cover}{
  \vspace*{-8pt}
  \noindent
  \includegraphics[width=10.35cm]{swufethesis-swufetitle.pdf}
  \vspace{64pt}
  \begin{center}
    {
      \bfseries
      \xeCJKsetup{ CJKecglue = {\hskip 10pt} }
      \fontsize{36bp}{3\dimexpr 15.6pt}\selectfont
      \CJKfamily+{zhhei}
      \swufe@index 届\\
      本科毕业论文（设计）\par
      \xeCJKsetup{ CJKecglue = { ~ } }
    }
    \vspace{66.5pt}
    \CJKfamily+{zhfs}
    \noindent
    \fontsize{16bp}{2\dimexpr 15.6pt}\selectfont
%    \end{macrocode}
% 下划线部分使用\pkg{xeCJKfntef}的\cs{CJKunderline*}实现（星号版本将不会跳过中文标点）。
% 注意 \verb|\\| 前面的空白，如果去除的话，在载入 \pkg{siunitx} 后，表格会向右对齐。原因尚不明确。
%    \begin{macrocode}
    {
    \def\swufe@@item##1:##2 {%
    {\bfseries ##1：}&{\CJKfamily+{hwfs}\swufe@conditional@center@underline{##2}} \\}
    \begin{tabular}{lp{252.1pt}}
      \swufe@@item 论文题目:\swufe@title{}
      \swufe@@item 学生姓名:\swufe@author{}
      \swufe@@item {所在学院}:\swufe@school{}
      \swufe@@item {专\hspace{2em}业}:\swufe@discipline{}
      \swufe@@item {学\hspace{2em}号}:\swufe@student@id{}
      \swufe@@item {指导教师}:\swufe@supervisor{}
      \swufe@@item {成\hspace{2em}绩}:{}
    \end{tabular}
    }
    \vspace{\fill}

    {
      \bfseries\swufe@date@format{\swufe@date}{\swufe@date@zh@digit@short}
    }
  \end{center}
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@make@postgraduate@cover}
% 研究生封面。文件 \textsf{swufethesis-thesistitle-master.pdf} 来源：将位图用 \textsf{Vectorizer.AI} 矢量化得到。
%    \begin{macrocode}
\newcommand{\swufe@make@postgraduate@cover}{%
  \def\swufe@@item##1:##2 {%
    \makebox[5em][s]{##1}&\swufe@conditional@center@underline{##2} \\
  }%
  \begingroup%
    \setlength{\parindent}{0pt}%
    \setlength{\tabcolsep}{0pt}%
    \includegraphics[height=1.9cm]{swufethesis-swufetitle-green.pdf}\par%
    \vspace{1.5cm}%
    \begin{center}
      \includegraphics[width=10.73cm]{swufethesis-thesistitle-master.pdf}\par%
      \vspace{22bp}%
      \CJKfamily{hwzs}\bfseries%
      \begingroup
        \fontsize{22bp}{30bp}\selectfont%
        \textbf{\swufe@title}\par%
      \endgroup
      \vspace{22bp}%
      \begingroup
        \fontsize{14bp}{19bp}\selectfont%
        \textbf{\swufe@title@en}\par%
      \endgroup
      \vspace{3cm}%
      \fontsize{18bp}{36bp}\selectfont%
      \begin{tabular}{c@{\hspace{1em}}p{235pt}}
        \swufe@@item 学位申请人:{\ifswufe@usage@anon\else\swufe@author\fi}
        \swufe@@item 指\hfil 导\hfil 教\hfil 师:{\ifswufe@usage@anon\else\swufe@supervisor\fi}
        \swufe@@item 学\hfil 科\hfil 专\hfil 业:\swufe@discipline{}
        \swufe@@item 学\hfil 位\hfil 类\hfil 别:\swufe@degree@in{}
      \end{tabular}
    \end{center}
  \endgroup
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@make@postgraduate@titlepage}
% 研究生扉页。
% 如前所述，页码计数不应该从封面开始，如果 \cs{maketitle} 前使用了 \cs{frontmatter}，则从扉页开始计数。
%    \begin{macrocode}
\newcommand{\swufe@make@postgraduate@titlepage}{%
  \ifswufe@frontmatter%
    \ifswufe@degree@bachelor%
      \pagenumbering{arabic}%
    \else%
      \pagenumbering{Roman}%
    \fi%
  \fi%
  \begingroup
  \setlength{\parindent}{0pt}
  \setlength{\tabcolsep}{0pt}
  \CJKfamily{zhhei}
  \fontsize{16bp}{32pt}\selectfont
  \begin{tabular}{p{.5\textwidth}p{.5\textwidth}}
    分类号\CJKunderline{\hfill\swufe@clc\hfill} &
    密级\CJKunderline{\hfill\swufe@secret@level\hfill} \\
    \multicolumn{2}{l}{\textsf{U.D.C}\hspace{6pt}\CJKunderline{\hfill\swufe@udc\hfill}}
  \end{tabular}

  \begin{center}
    \fontsize{18bp}{2\dimexpr 15.6pt}\selectfont
    \CJKfamily{hwzs}
    \ifswufe@degree@type@equivalent%
      \vspace{24pt}
      \textbf{具有研究生毕业同等学力人员申请硕士学位学位论文}
    \fi

    \vspace{52pt}
    \textbf{\swufe@title}

    \vspace{23pt}
    \fontsize{12bp}{15.6pt}\selectfont
    \textbf{\swufe@title@en}

    \vfill
    \def\swufe@@item##1:##2 {%
      \makebox[5em][s]{##1}&\swufe@conditional@center@underline{##2} \\
    }
    \ifswufe@degree@type@equivalent%
      \fontsize{15bp}{37pt}\selectfont
    \else%
      \fontsize{15bp}{35pt}\selectfont
    \fi%
    \CJKfamily+{zhhei}
    \def\swufe@@issue@date{%
      \swufe@date@format{\swufe@date}{\swufe@date@zh@digit}%
    }
    \begin{tabular}{c@{：}p{235pt}}
      \swufe@@item 学位申请人:{\ifswufe@usage@anon\else\swufe@author\fi}
      \ifswufe@degree@type@equivalent\else%
        \swufe@@item 学\hfil 号:{\ifswufe@usage@anon\else\swufe@student@id\fi}
      \fi%
      \swufe@@item 学\hfil 科\hfil 专\hfil 业:\swufe@discipline{}
      \swufe@@item 研\hfil 究\hfil 方\hfil 向:\swufe@research@field{}
      \swufe@@item 指\hfil 导\hfil 教\hfil 师:{\ifswufe@usage@anon\else\swufe@supervisor\fi}
      \swufe@@item 定\hfil 稿\hfil 时\hfil 间:\swufe@@issue@date{}
    \end{tabular}
    \ifswufe@degree@type@equivalent%
      \vspace{140pt}
    \else%
      \vspace{220pt}
    \fi
  \end{center}
  \endgroup
}
%    \end{macrocode}
% \end{macro}
% \subsection{学术申明}
% \begin{macro}{\statement}
% 定义\cs{statement}命令打印学术申明页。
%    \begin{macrocode}
\newcommand{\statement}{
  \ifswufe@usage@check\else%
    \begin{swufe@msword@geometry}
      \cleardoublepage%
      \thispagestyle{empty}%
      \ifswufe@degree@bachelor%
        \swufe@make@bachelor@statement%
      \else%
        \swufe@make@postgraduate@statement%
      \fi%
    \end{swufe@msword@geometry}
  \fi
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@make@bachelor@statement}
% 本科生学术申明。
%^^A 这里不设置vspace时第一行字将紧挨着页面的body部分（可设置geometry的showframe选项查看）
%^^A 没搞清原理
%    \begin{macrocode}
\newcommand{\swufe@make@bachelor@statement}{
  \vspace*{-34pt}
  \begin{center}
    \bfseries
    \CJKfamily{hwzs}
    \fontsize{18bp}{2\dimexpr 15.6pt}\selectfont
    西南财经大学\\
    本科毕业论文原创性及知识产权声明\par
  \end{center}
  \vspace{12.3pt}

  \fontsize{12bp}{1.4\dimexpr 15.6pt}\selectfont
  本人郑重声明：所呈交的毕业论文是本人在导师的指导下取得的成果，论文
  写作严格遵循学术规范。对本论文的研究做出重要贡献的个人和集体，均已在文
  中以明确方式标明。因本毕业论文引起的法律结果完全由本人承担。

  本毕业论文成果归西南财经大学所有。
  \vspace{2\dimexpr 15.6pt}

  特此声明
  \vspace{\fill}
  \begin{flushright}
    毕业论文作者签名：\hspace*{4em}

    作者专业：\hspace*{4em}

    作者学号：\hspace*{4em}

    \swufe@date@format{\swufe@date}{\swufe@date@zh@digit}
  \end{flushright}
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@make@postgraduate@statement}
% 研究生学术申明
%    \begin{macrocode}
\newcommand{\swufe@make@postgraduate@statement}{
  \vspace*{-18pt}
  \begin{center}
    \fontsize{18bp}{2\dimexpr 15.6pt}\selectfont
    \CJKfamily{zhsong}\bfseries
    西南财经大学学位论文原创性及知识产权声明
  \end{center}

  \vspace{2pt}
  \begingroup
  \CJKfamily+{zhfs}
  \bfseries
  \fontsize{16bp}{28pt}\selectfont
  本人郑重声明：所呈交的学位论文，是本人在导师的指
  导下独立进行研究工作所取得的成果。除文中已经注明引用
  的内容外，本论文不含任何其他个人或集体已经发表或撰写
  过的作品成果。对本文的研究做出重要贡献的个人和集体，
  均已在文中以明确方式标明，因本学位论文引起的法律结果
  完全由本人承担。

  \vspace{16pt}
  \fontsize{16bp}{25pt}\selectfont
  本人同意在校攻读学位期间论文工作的知识产权单位
  属西南财经大学。本人完全了解西南财经大学有关保留、使
  用学位论文的规定，即学校有权保留并向国家有关部门或机
  构送交论文的复印件和电子版，允许论文被查阅和借阅。本
  人授权西南财经大学可以将本学位论文的全部或部分内容
  编入有关数据库进行检索，可以采用影印、缩印、数字化或
  其他复制手段保存和汇编本学位论文。

  \vspace{14pt}
  \noindent 本学位论文属于

%    \end{macrocode}
% 勾选框
%    \begin{macrocode}
  \setlength{\fboxrule}{1.2pt}%
  \setlength{\fboxsep}{0pt}%
  \def\swufe@@checkbox{%
    \makebox[11pt][l]{%
      \makebox[0pt][l]{\framebox[13pt]{\parbox{0pt}{\vspace{10pt}}}}%
      $\checkmark$%
    }
  }
  \def\swufe@@emptybox{%
    \makebox[11pt][l]{%
      \framebox[13pt]{\parbox{0pt}{\vspace{10pt}}}%
    }
  }

  \def\swufe@@secret@year{%
    \underline{\raisebox{-1pt}{\makebox[41pt]{\hfil\swufe@secret@year\hfil}}}%
  }
%    \end{macrocode}
% 根据\cs{swufe@secret@year}是否为空来判断是否是公开的
%    \begin{macrocode}
  \newif\ifswufe@@secret@level@public
  \ifx\swufe@secret@year\@empty%
    \swufe@@secret@level@publictrue
  \fi%

  \vspace{14pt}
%    \end{macrocode}
% 取消CJK与英文字符间距，这个影响是局部的
%    \begin{macrocode}
  \xeCJKsetup{ CJKecglue = {} }
  \noindent 1、\ifswufe@@secret@level@public\swufe@@emptybox\else\swufe@@checkbox\fi
  保密，在\swufe@@secret@year 年解密后适用本授权书。

  \vspace{14pt}
  \noindent 2、\ifswufe@@secret@level@public\swufe@@checkbox\else\swufe@@emptybox\fi 不保密
%    \end{macrocode}
% 下面的日期之间还是需要间距。
%    \begin{macrocode}
  \xeCJKsetup{ CJKecglue = {~} } 

  \vspace{14pt}
  \noindent 特此声明。

  \begin{flushright}
    学位申请人：\hspace{4em}

    \vspace{14pt}
    \swufe@date@format{\swufe@date}{\swufe@date@zh@digit}
  \end{flushright}
  \endgroup
}
%    \end{macrocode}
% \end{macro}
% \subsection{封底}
% \begin{macro}{\swufe@make@postgraduate@backcover}
% 本科生封底。封底主要由校训（华文行楷，MS Word 制作）和光华铁树\footnote{提取自财大《视觉形象识别系统 UIS 导入与实施》，网址：\url{https://office.swufe.edu.cn/__local/6/7B/CF/54FB3E5ADE2CE5B10B6699DD4E1_B08122FF_1CB2319.pdf}}（颜色 |#969595|） 叠加而成。
% 这里通过类似于 \cs{llap} 的方式来实现叠加\footnote{\url{https://tex.stackexchange.com/a/573077}}。
% 即在铁树的后面通过 \cs{makebox} 放置图片于的插入点左侧，从而通过末尾的 \cs{hspace} 增加空白来调整左右位置，并通过 \cs{raisebox} 调整上下位置。
%    \begin{macrocode}
\newcommand{\swufe@make@bachelor@backcover}{%
  \begin{swufe@msword@geometry}
    \thispagestyle{empty}%
    \vspace*{112bp}%
    \begin{center}
      \includegraphics[width=8.66cm]{swufethesis-swufecycas.pdf}%
      \makebox[0pt][r]{% Similar to \llap
        \raisebox{-13bp}{%
          \includegraphics[width=168bp]{swufethesis-swufemotto-vert}%
        }\hspace*{1.5cm}%
      }%
    \end{center}
  \end{swufe@msword@geometry}
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@make@postgraduate@backcover}
% 研究生封底。封底校训、校址信息等矢量图采用 MS Word 制作。
% 校训用华文行楷，颜色 |#595758|，并附有阴影效果；
% 封底信息部分，英文使用 Times New Roman 加粗，中文用方正小标宋简体（不加粗）。
%    \begin{macrocode}
\newcommand{\swufe@make@postgraduate@backcover}{%
  \begin{swufe@msword@geometry}
    \thispagestyle{empty}%
    \begin{center}
      \includegraphics[width=2.7cm]{swufethesis-swufeemblem-black.pdf}\par%
      \vspace{1.4cm}%
      \includegraphics[width=9cm]{swufethesis-swufemotto-horiz}\par%
      \vspace{8.5cm}%
      \includegraphics[width=12cm]{swufethesis-gradbackinfo.pdf}\par%
    \end{center}
  \end{swufe@msword@geometry}
}
%    \end{macrocode}
% \end{macro}
% 通过钩子设置封底。
% \begin{macrocode}
\AtEndDocument{%
  \ifswufe@usage@check\else%
    \cleardoublepage%
    \ifswufe@output@electronic\else%
      \null\thispagestyle{empty}\newpage%
    \fi%
    \ifswufe@degree@bachelor%
      \swufe@make@bachelor@backcover%
    \else%
      \swufe@make@postgraduate@backcover%
    \fi%
  \fi%
}
%    \end{macrocode}
%
% \subsection{字体}
% 判断操作系统，这是判断字体方案自动选取的依据之一。
%    \begin{macrocode}
\newif\ifswufe@system@windows
\newif\ifswufe@system@mac
\newif\ifswufe@system@unix
\IfFileExists{/System/Library/Fonts/Menlo.ttc}{%
  \swufe@system@mactrue%
}{%
  \IfFileExists{/dev/null}{%
    \IfFileExists{null:}{%
      \swufe@system@windowstrue%
    }{%
      \swufe@system@unixtrue%
    }
  }{%
    \swufe@system@windowstrue%
  }%
}
%    \end{macrocode}
% \subsubsection{中文字体}
%    \begin{macrocode}
\xeCJKsetup{%
  AutoFakeBold = true
}
%    \end{macrocode}
% \begin{macro}{\swufe@set@cjk@font@fandol}
% \textsf{fandol}方案。
%    \begin{macrocode}
\newcommand{\swufe@set@cjk@font@fandol}{%
  \setCJKmainfont{FandolSong}[
    Extension = .otf,
    UprightFont = *-Regular,
    BoldFont = *-Bold,
    ItalicFont = FandolKai-Regular,
  ]%
  \setCJKsansfont{FandolHei}[
    Extension = .otf,
    UprightFont = *-Regular,
    BoldFont = *-Bold,
  ]%
  \setCJKmonofont{FandolFang}[
    Extension = .otf,
    UprightFont = *-Regular,
  ]%
  \setCJKfamilyfont{zhsong}{FandolSong}[
    Extension = .otf,
    UprightFont = *-Regular,
    BoldFont = *-Bold,
  ]%
  \setCJKfamilyfont{zhhei}{FandolHei}[
    Extension = .otf,
    UprightFont = *-Regular,
    BoldFont = *-Bold,
  ]%
  \setCJKfamilyfont{zhfs}{FandolFang}[
    Extension = .otf,
    UprightFont = *-Regular,
  ]%
  \setCJKfamilyfont{zhkai}{FandolKai}[
    Extension = .otf,
    UprightFont = *-Regular,
  ]%
  \def\swufe@hwfs@fallback{%
    \setCJKfamilyfont{hwfs}{FandolFang}[
      Extension = .otf,
      UprightFont = *-Regular,
    ]%
  }
  \def\swufe@hwzs@fallback{%
    \setCJKfamilyfont{hwzs}{FandolSong}[
      Extension = .otf,
      UprightFont = *-Regular,
      BoldFont = *-Bold,
    ]%
  }
  \def\swufe@xbs@fallback{%
    \setCJKfamilyfont{xbs}{FandolSong}[
      Extension = .otf,
      UprightFont = *-Regular,
      BoldFont = *-Bold,
    ]%
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@set@cjk@font@noto}
% \textsc{noto}方案。
%    \begin{macrocode}
\newcommand{\swufe@set@cjk@font@noto}{%
  \setCJKmainfont{Noto Serif CJK SC}[
    UprightFont = * Light,
    BoldFont = * Bold,
    ItalicFont = FandolKai-Regular,
    ItalicFeatures = {Extension = .otf},
  ]%
  \setCJKsansfont{Noto Sans CJK SC}[
    BoldFont = * Medium,
  ]%
  \setCJKmonofont{Noto Sans Mono CJK SC}%
  \setCJKfamilyfont{zhsong}{Noto Serif CJK SC}[
    UprightFont = * Light,
    BoldFont = * Bold,
  ]%
  \setCJKfamilyfont{zhhei}{Noto Sans CJK SC}[
    BoldFont = * Medium,
  ]%
  \setCJKfamilyfont{zhfs}{FandolFang}[
    Extension = .otf,
    UprightFont = *-Regular,
  ]%
  \setCJKfamilyfont{zhkai}{FandolKai}[
    Extension = .otf,
    UprightFont = *-Regular,
  ]%
  \def\swufe@hwfs@fallback{%
    \setCJKfamilyfont{hwfs}{FandolFang}[
      Extension = .otf,
      UprightFont = *-Regular,
    ]%
  }
  \def\swufe@hwzs@fallback{%
    \setCJKfamilyfont{hwzs}{Noto Serif CJK SC}%
  }
  \def\swufe@xbs@fallback{%
    \setCJKfamilyfont{xbs}{Noto Serif CJK SC}%
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@set@cjk@font@mac}
% \textsf{mac}方案。
%    \begin{macrocode}
\newcommand{\swufe@set@cjk@font@mac}{%
  \setCJKmainfont{Songti SC}[
    UprightFont = * Light,
    BoldFont = * Bold,
    ItalicFont = Kaiti SC,
    BoldItalicFont = Kaiti SC Bold,
  ]%
  \setCJKsansfont{Heiti SC}[
    BoldFont= * Medium
  ]%
  \setCJKmonofont{STFangsong}
  \setCJKfamilyfont{zhsong}{Songti SC}[
    UprightFont = * Light,
    BoldFont = * Bold,
  ]%
  \setCJKfamilyfont{zhhei}{Heiti SC}[
    UprightFont = * Light,
    BoldFont = * Medium,
  ]%
  \setCJKfamilyfont{zhfs}{STFangsong}%
  \setCJKfamilyfont{zhkai}{Kaiti SC}[
    BoldFont = * Bold
  ]%
  \def\swufe@hwzs@fallback{%
    \setCJKfamilyfont{hwzs}{Songti SC}[
      UprightFont = * Light,
      BoldFont = * Bold,
    ]%
  }
  \def\swufe@xbs@fallback{%
    \setCJKfamilyfont{xbs}{Songti SC}[
      UprightFont = * Light,
      BoldFont = * Bold,
    ]%
  }
  \def\swufe@hwfs@fallback{%
    \setCJKfamilyfont{zhfs}{STFangsong}%
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@set@cjk@font@windows}
% \textsf{windows}方案
%    \begin{macrocode}
\newcommand{\swufe@set@cjk@font@windows}{%
  \xeCJKsetup{EmboldenFactor=3}%
  \setCJKmainfont{SimSun}[
    ItalicFont = KaiTi,
  ]%
  \setCJKsansfont{SimHei}%
  \setCJKmonofont{FangSong}%
  \setCJKfamilyfont{zhsong}{SimSun}%
  \setCJKfamilyfont{zhhei}{SimHei}%
  \setCJKfamilyfont{zhkai}{KaiTi}%
  \setCJKfamilyfont{zhfs}{FangSong}%
  \def\swufe@hwfs@fallback{%
    \setCJKfamilyfont{hwfs}{FangSong}%
  }
  \def\swufe@hwzs@fallback{%
    \setCJKfamilyfont{hwzs}{SimSun}%
  }
  \def\swufe@xbs@fallback{%
    \setCJKfamilyfont{hwzs}{SimSun}%
  }
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@set@cjk@font@auto}
% \textsf{auto}方案，根据一些条件从上述方案中自动选取。
%    \begin{macrocode}
\newcommand{\swufe@set@cjk@font@auto}{%
  \ifswufe@system@mac%
    \IfFontExistsTF{Kaiti SC}{%
      \swufesetup{ cjk-font = mac }%
      \swufe@set@cjk@font@mac
    }{}%
  \fi
  \ifswufe@system@windows%
    \IfFontExistsTF{KaiTi}{%
      \swufesetup{ cjk-font = windows }%
      \swufe@set@cjk@font@windows
    }{}%
  \fi
  \ifswufe@system@unix%
    \IfFontExistsTF{Noto Serif CJK SC}{%
      \IfFontExistsTF{Noto Sans CJK SC}{%
        \swufesetup{ cjk-font = noto }%
        \swufe@set@cjk@font@noto
      }{}%
    }{}%
  \fi

  \ifswufe@cjk@font@auto%
%    \end{macrocode}
% 以上方案均未设置，采用fandol方案
%    \begin{macrocode}
    \swufesetup{ cjk-font = fandol }%
    \swufe@set@cjk@font@fandol
  \fi
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@set@cjk@font@auto}
% \textsf{none}方案，不作设置。
% 需要用户自行设置 \textsf{zhsong}、\textsf{zhhei}、\textsf{zhfs}、\textsf{zhkai}、\textsf{hwzs}、\textsf{hwfs}、\textsf{xbs} 等 CJK 字体，
% （它们分别代表宋体、黑体、仿宋、楷体等基础字体，以及特别要求的华文中宋、华文仿宋、小标宋，）
% 以及设置 \cs{setCJKmainfont}、\cs{setCJKsansfont} 和 \cs{setCJKmonofont}。
%    \begin{macrocode}
\newcommand{\swufe@set@cjk@font@none}{%
  \providecommand{\swufe@hwzs@fallback}{}
  \providecommand{\swufe@hwfs@fallback}{}
  \providecommand{\swufe@xbs@fallback}{}
}
%    \end{macrocode}
% \end{macro}
% Preamble结束前设置字体。
%    \begin{macrocode}
\AtEndPreamble{%
  \@nameuse{swufe@set@cjk@font@\@nameuse{swufe@cjk@font}}%
  \ifswufe@cjk@font@none\else%
    \providecommand{\heiti}{\CJKfamily{zhhei}}
    \providecommand{\fangsong}{\CJKfamily{zhfs}}
    \providecommand{\songti}{\CJKfamily{zhsong}}
    \providecommand{\kaishu}{\CJKfamily{zhkai}}
  \fi
}
%    \end{macrocode}
% 一级标题中的华文中宋与封面的华文仿宋属于硬性规定，独立于前面的cjk-font设定
% 如果找不到相应的字体会fallback至前面cjk-font
%    \begin{macrocode}
\AtBeginDocument{%
  \swufe@hwzs@fallback
  \swufe@hwfs@fallback
  \swufe@xbs@fallback
}
%    \end{macrocode}
%
% \subsubsection{英文字体}
% \begin{macro}{\swufe@set@font@times}
% \textsf{times}方案。
%    \begin{macrocode}
\newcommand{\swufe@set@font@times}{%
  \setmainfont{Times New Roman}%
  \setsansfont{Arial}%
  \ifswufe@system@mac%
    \setmonofont{Menlo}%
  \else%
    \setmonofont{Courier New}%
  \fi
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\swufe@set@font@termes}
% \textsf{termes}方案。
%    \begin{macrocode}
\newcommand{\swufe@set@font@termes}{%
  \setmainfont{texgyretermes}[
    Extension = .otf,
    UprightFont = *-regular,
    BoldFont = *-bold,
    ItalicFont = *-italic,
    BoldItalicFont = *-bolditalic,
  ]%
  \setsansfont{texgyreheros}[
    Extension = .otf,
    UprightFont = *-regular,
    BoldFont = *-bold,
    ItalicFont = *-italic,
    BoldItalicFont = *-bolditalic,
  ]%
  \setmonofont{texgyrecursor}[
    Extension = .otf,
    UprightFont = *-regular,
    BoldFont = *-bold,
    ItalicFont = *-italic,
    BoldItalicFont = *-bolditalic,
  ]%
}
%    \end{macrocode}
% \end{macro}
%    \begin{macrocode}
\swufe@option@hook{font}{%
  \@nameuse{swufe@set@font@\@nameuse{swufe@font}}%
}
%    \end{macrocode}
% \begin{macro}{\swufe@set@font@auto}
% \textsf{auto}方案。
%    \begin{macrocode}
\newcommand{\swufe@set@font@auto}{%
  \ifswufe@system@unix%
    \IfFontExistsTF{texgyretermes-regular.otf}{%
      \swufesetup{ font = termes }%
    }{}%
  \else%
%    \end{macrocode}
% Windoes与Mac采用\textsf{times}方案
%    \begin{macrocode}
    \swufesetup{ font = times }%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{默认值设置}
% 直接调用\cs{swufesetup}设置一组默认值。
%    \begin{macrocode}
\swufesetup{
%    \end{macrocode}
% 例如2020年9月（含）至2021年9月（不含）设定为2021届
%    \begin{macrocode}
  index = \swufe@date@format{\swufe@date}{\swufe@index@formatter},
  date = {\the\year-\swufe@twodigits\month-\swufe@twodigits\day},
  font = auto,
  cjk-font = auto,
  secret-year = {},
  secret-level = {},
  degree = bachelor,
  degree-type = academic,
  output = print,
  usage = normal,
}
%    \end{macrocode}
%
% \subsection{其他}
% 定义一些与项目本身有关的命令。
% \begin{macro}{\SwufeThesis}
% \cs{SwufeThesis}与\cs{swufethesis}打印\swufethesis{}，可以作为项目的标识。
%    \begin{macrocode}
\newcommand{\SwufeThesis}{\textsc{Swufe\-Thesis}}
\let\swufethesis\SwufeThesis
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\swufeversion}
% \cs{swufeversion}打印当前版本，\cs{swufedate}打印发布日期。
%    \begin{macrocode}
\newcommand{\swufeversion}{1.0.0-alpha.0}
\newcommand{\swufedate}{2021/03/15}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\swufeanonmask}
% 研究生的学位论文需要提交匿名版，即使是致谢里的信息也需要匿名化处理。这里提供一个宏使得能够根据 |output| 的选项来自动匿名其参数。
% \cs{swufeanonmask} \oarg{alter} \marg{text} 在 |output = anon| 时会将 \meta{text} 输出成固定长度的空白；
% 如果给定了可选参数 \meta{alter}，则输出该参数；在其他情况下原样输出。
% 而变体 \cs{swufeanonmask*}\marg{text} 输出的空白的长度与 \meta{text} 相同，相当于 \cs{phantom}。
% 变体 \cs{swufeanonmask-}\marg{text} 则在匿名时完全不输出。
%    \begin{macrocode}
\NewDocumentCommand{\swufeanonmask}{s t- o m}{%
  \ifswufe@usage@anon%
    \IfBooleanTF{#2}{}{%
      \IfBooleanTF{#1}{%
        \phantom{#4}%
      }{%
        \IfValueTF{#3}{#3}{\hspace{2em}}%
      }%
    }%
  \else#4\fi%
}
%    \end{macrocode}
% \end{macro}
% \Finale
